package com.beautify.websocket;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
@ServerEndpoint("/peerServerEndpoint/{peerId}/{userTypes}")
public class MatchServerEndpoint {

    // 只保留志愿者的集合
    // true 代表 空闲， false 代表 忙碌
    private static final Map<String, Boolean> volPeerIdMap = new ConcurrentHashMap<>();


    // 声明一个私有变量session
    private Session session;

    @OnOpen
    public void onOpen(Session session, @PathParam("peerId") String peerId, @PathParam("userTypes") String types) {
        log.info("on open:the session is  :{},the peer id is:{},the user types is:{}", session.getId(), peerId, types);
        this.session = session;

        if (types.equals("1")) {
            volPeerIdMap.put(peerId, true);
        }
        log.info("the volPeerIdMap size : {}", MatchServerEndpoint.volPeerIdMap.keySet());
    }


    /*规定：
     *  前端发送的消息格式为：
     *     {
     *         "message": "startMatch" // 开始匹配
     *     }
     *  或者
     *     {
     *         "volPeerId": "志愿者的 peerId",
     *         "message": "endMatch" // 结束匹配/挂断
     *     }
     *
     *   如果 volPeerId 为 -1000，说明没有匹配到志愿者，则不做任何处理，否则将志愿者的状态更改为空闲
     * */
    @OnMessage
    public void onMessage(Session session, String msgAndPeerId) {
        try {
            // 解析前端发送的消息
            JSONObject jsonObject = JSON.parseObject(msgAndPeerId);

            // 解析志愿者的 peerId
            String volPeerId = "-1000";
            if (jsonObject.containsKey("volPeerId")) {
                volPeerId = jsonObject.getString("volPeerId");
            }
            String message = jsonObject.getString("message");

            // 根据消息类型进行处理
            if (message.equals("startMatch")) {
                startMatchAndSendVolPeerId(message);
            } else {
                endMatchAndChangeVolStatus(message, volPeerId);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @OnClose
    public void onClose(Session session, @PathParam("peerId") String peerId) {
        log.warn("on close:the session is is :{},the peer id is:{}", session.getId(), peerId);
        if (peerId != null) {
            volPeerIdMap.remove(peerId);
            log.info("the volPeerIdMap size : {}", MatchServerEndpoint.volPeerIdMap.keySet());

        }
        try {
            this.session.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @OnError
    public void onError(Session session, Throwable e, @PathParam("peerId") String peerId) {
        log.error("on error:the session is is :{},the exception class is: {},the peer id is:{}", session.getId(), e.getClass(), peerId);
        onClose(session, peerId);
        log.info("the volPeerIdMap size : {}", MatchServerEndpoint.volPeerIdMap.keySet());

        try {
            this.session.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            MatchServerEndpoint.volPeerIdMap.remove(peerId);
            log.info("Error: the volPeerIdMap size is: {}", MatchServerEndpoint.volPeerIdMap.size());
        }
        e.printStackTrace();
    }

    // 发送 志愿者的 peerId 返回给前端
    public void sendVolPeerId(String volPeerId) {
        log.info("send volPeerId: {}", volPeerId);
        synchronized (this.session) {
            try {
                this.session.getBasicRemote().sendText(volPeerId);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    // 前端发送 -> 开始匹配
    public void startMatchAndSendVolPeerId(String msg) {
        log.info("开始匹配 ---> {}", msg);
        // 在 志愿者列表中找到匹配的志愿者
        // 在 volPeerIdMap 中找到第一个空闲的志愿者
        if (!volPeerIdMap.isEmpty()) {
            // 找到第一个空闲的志愿者
            Optional<String> volPeerIdOptional; // 查找第一个空闲的志愿者

            for (int i = 0; i < 1000; i++) {
                volPeerIdOptional = volPeerIdMap.entrySet().stream()
                        .filter(entry -> entry.getValue().equals(true)) // 过滤出空闲的志愿者
                        .map(Map.Entry::getKey) // 提取志愿者的 peerId
                        .findAny(); // 查找第一个空闲的志愿者
                // 如果找到了空闲的志愿者，发送他的 peerId 给前端，并将其状态更改为忙碌
                if (volPeerIdOptional.isPresent()) {
                    String volPeerId = volPeerIdOptional.get();
                    // 更新志愿者的状态为忙碌
                    volPeerIdMap.put(volPeerId, false);
                    // 发送 志愿者的 peerId 返回给前端
                    sendVolPeerId(volPeerId);
                    break;
                }
            }
        } else {
            // 如果志愿者列表为空，处理这种情况
            log.info("志愿者列表为空");
            // 可以选择发送一个错误消息给前端或者执行其他逻辑
            log.info("the volPeerIdMap size : {}", MatchServerEndpoint.volPeerIdMap.keySet());
            sendVolPeerId("-1000");
        }
    }

    // 前端发送 -> 结束匹配/挂断
    public void endMatchAndChangeVolStatus(String msg, String volPeerId) {
        log.info("结束匹配 ---> {}", msg);
        // 找到匹配的志愿者
        // 将其状态更改为空闲
        // volPeerId 不一定会发送给了前端，所以需要判断一下
        // 如果 volPeerId 为空，说明没有匹配到志愿者，则不做任何处理，否则将志愿者的状态更改为空闲
        if (!volPeerId.equals("-1000") && volPeerIdMap.containsKey(volPeerId)) {
            volPeerIdMap.put(volPeerId, true);
        }
    }
}
